package eu.robico.simulator.simulatorinterface.actionpanel.objects;

import java.awt.Color;
import java.awt.Graphics2D;

import eu.robico.simulator.simulatorinterface.MainController;
import eu.robico.simulator.simulatorinterface.actionpanel.Position;
import eu.robico.simulator.simulatorinterface.communication.Protocol.Trigger;

/**
 * Represents a object that can detect wheter or not it is positioned above a color lane.
 * @author A.J. Janssen
 * @version 0.4
 *
 */
class ColorLaneSensor implements RobotComponent
{
	public enum ColorLaneSensorPosition
	{
		CENTRALLEFT,
		CENTRALRIGHT,
		OUTERLEFT,
		OUTERRIGHT;
	}
	/**
	 * Represents a on-screen color lane sensor object.
	 * @author A.J. Janssen
	 * @version 0.1
	 *
	 */
	private class ColorLaneSensorObject
	{
		public void paint(Graphics2D graphics) 
		{
			Color sensorColor = (sensorActive) ? Color.green : Color.blue;
			graphics.setColor(sensorColor);
			graphics.fillOval((int) x - (size / 2), (int) y - (size / 2), size, size);
			
//			if (centerPosition != null)
//			{
//				graphics.setColor(Color.pink);
//				graphics.fillOval((int) centerPosition.x - 3, (int) centerPosition.y - 3, 6, 6);
//			}
		}
	}
	
	private ColorLaneSensorPosition colorLaneSensorPosition;
	private ColorLaneSensorObject sensorObject;
	private Robot robot;
	private Position centerPosition;
	private int size = 8;
	private double x, y, rotation, distanceToRobotCenter;
	private boolean sensorActive = false;
	
	public ColorLaneSensor(Robot robot, Position location, double rotation, ColorLaneSensorPosition colorLaneSensorPosition)
	{
		this.robot = robot;
		this.x = location.x;
		this.y = location.y;
		this.rotation = rotation;
		this.colorLaneSensorPosition = colorLaneSensorPosition;
		sensorObject = this.new ColorLaneSensorObject();
	}
	
	private boolean isOnColorLane(ColorLaneObject colorLane)
	{
		double minX, minY, maxX, maxY;
		if (colorLane.getStartPosition().x < colorLane.getEndPosition().x)
		{//Startpoint is on the left side of the endpoint
			minX = colorLane.getStartPosition().x - (colorLane.getWidth() / 2);
			maxX = colorLane.getEndPosition().x + (colorLane.getWidth() / 2);
		} else {
			minX = colorLane.getEndPosition().x - (colorLane.getWidth() / 2);
			maxX = colorLane.getStartPosition().x + (colorLane.getWidth() / 2);
		}
		if (colorLane.getStartPosition().y < colorLane.getEndPosition().y)
		{//Startpoint is above the endpoint
			minY = colorLane.getStartPosition().y - (colorLane.getWidth() / 2);
			maxY = colorLane.getEndPosition().y + (colorLane.getWidth() / 2);
		} else {
			minY = colorLane.getEndPosition().y - (colorLane.getWidth() / 2);
			maxY = colorLane.getStartPosition().y + (colorLane.getWidth() / 2);
		}
		
		return (centerPosition.x >= minX &&
				centerPosition.x <= maxX &&
				centerPosition.y >= minY &&
				centerPosition.y <= maxY);
	}
	
	//RobotComponent implementation below
	
	@Override
	public void update()
	{
		boolean oldSensorActive = sensorActive;
		sensorActive = false;
		for (ActionPanelObject object : robot.getActionPanel().getObjects())
			if ((object instanceof ColorLaneObject && isOnColorLane((ColorLaneObject) object)) ||
				(object instanceof CrossRoadsObject && ((CrossRoadsObject) object).containsPosition(centerPosition)))
			{
				if (!oldSensorActive) //just detected a new collision
					sendToggleTrigger();
				sensorActive = true;
				return;
			}
		//No activity detected
		if (oldSensorActive)
			sendToggleTrigger();
		sensorActive = false;
	}

	private void sendToggleTrigger()
	{
		Trigger trigger;
		switch (colorLaneSensorPosition)
		{
			case CENTRALLEFT: trigger = Trigger.COLORLANELEFTTOGGLE; break;
			case CENTRALRIGHT: trigger = Trigger.COLORLANERIGHTTOGGLE; break;
			case OUTERLEFT: trigger = Trigger.SIDEEXITLEFTTOGGLE; break;						
			case OUTERRIGHT: trigger = Trigger.SIDEEXITRIGHTTOGGLE; break;
			default: throw new IllegalStateException("Sensor is located at a unhandled position");
		}
		MainController.getInstance().sendTrigger(trigger);
	}
	
	@Override
	public double getRotation() 
	{
		return rotation;
	}

	@Override
	public void setRotation(double rotation) 
	{
		this.rotation = rotation;
	}

	@Override
	public void setTrueCenter(Position centerPoint) 
	{
		this.centerPosition = centerPoint;
	}

	@Override
	public Position getTrueCenter() 
	{
		return centerPosition;
	}
	
	@Override
	public double getX() 
	{
		return x;
	}

	@Override
	public double getY() 
	{
		return y;
	}

	@Override
	public void setX(double x) 
	{
		this.x = x;
	}

	@Override
	public void setY(double y) 
	{
		this.y = y;
	}

	@Override
	public RobotComponentType getType() 
	{
		return RobotComponentType.ColorLaneSensor;
	}

	@Override
	public Position getPosition() 
	{
		return new Position(x, y);
	}
	
	@Override
	public void paint(Graphics2D graphics) 
	{
		sensorObject.paint(graphics);
	}

	@Override
	public double getDistanceToRobotCenter() 
	{
		return distanceToRobotCenter;
	}

	@Override
	public void setDistanceToRobotCenter(double distanceToRobotCenter) 
	{
		this.distanceToRobotCenter = distanceToRobotCenter;
	}
}
